package com.component.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.component.domain.MChannel;
import com.component.domain.MModel;
import com.component.domain.vo.ModelChannelVo;
import com.component.enumitem.ModelComponentEnum;
import com.component.enumitem.NoteDataTypeEnum;
import com.component.service.MChannelService;
import com.component.service.MDictiService;
import com.component.service.MModelService;
import com.component.mapper.MModelMapper;
import com.system.util.FormulaUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 *
 */
@Service
public class MModelServiceImpl extends ServiceImpl<MModelMapper, MModel>
    implements MModelService{

    private String empty_table_="\n                                  ";

    private String empty_table="            ";

    @Autowired
    private MChannelService mChannelService;

    @Override
    public IPage<MModel> page(Integer pageNumber, Integer pageSize, String title) {
        LambdaQueryWrapper<MModel> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(title)){
            lambdaQueryWrapper.like(MModel::getModelTitle,title);
        }
        lambdaQueryWrapper.orderByDesc(MModel::getCreateTime);
        IPage<MModel> mModelIPage=this.page(new Page(pageNumber,pageSize),lambdaQueryWrapper);
        return mModelIPage;
    }

    @Override
    public boolean bindChannelModel(ModelChannelVo vo) {
        MModel mModel=this.getById(vo.getId());
        if(mModel==null){
            return false;
        }
        MChannel mChannel=mChannelService.getById(vo.getChannelId());
        if(mChannel == null){
            return false;
        }
        LambdaUpdateWrapper<MModel> updateWrapper=new LambdaUpdateWrapper<>();
        updateWrapper.set(MModel::getChannelId,null);
        updateWrapper.eq(MModel::getChannelId,vo.getChannelId().toString());
        this.baseMapper.update(null,updateWrapper);
        mModel.setChannelId(vo.getChannelId().toString());
        this.updateById(mModel);
        mChannel.setModelId(mModel.getId().toString());
        mChannelService.updateById(mChannel);

        return true;
    }

    @Override
    public List<String> getComponentsByModel(MModel mModel) {
        List<String> strings=new ArrayList<>();
        if(mModel.getModelJson()!=null){
            JSONArray array=JSONArray.parseArray(mModel.getModelJson());
            List<String> fields=new ArrayList<>();
            for (int i = 0; i < array.size(); i++) {
                JSONObject obj = array.getJSONObject(i);
                fields.add(obj.getString("field"));
            }
            for (int i = 0; i < array.size(); i++) {
                JSONObject obj=array.getJSONObject(i);
                String str=createComponent(obj,fields);
                strings.add(str);
                System.out.println(str);
            }
        }
        return strings;
    }

    @Override
    public List<String> getComponentsByArray(JSONArray array) {
        List<String> strings=new ArrayList<>();
        //获取所有的字段
        List<String> fields=new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj = array.getJSONObject(i);
            fields.add(obj.getString("field"));
        }
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj=array.getJSONObject(i);
            String str=createComponent(obj,fields);
            strings.add(str);
            System.out.println(str);
        }
        return strings;
    }

    @Override
    public List<String> getTablesByModel(MModel mModel) {
        List<String> strings=new ArrayList<>();
        if(mModel.getModelJson()!=null){
            JSONArray array=JSONArray.parseArray(mModel.getModelJson());
            for (int i = 0; i < array.size(); i++) {
                JSONObject obj=array.getJSONObject(i);
                String str=createTable(obj);
                strings.add(str);
            }
        }
        return strings;
    }

    @Override
    public List<String> getTablesByArray(JSONArray array) {
        List<String> strings=new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj=array.getJSONObject(i);
            String str=createTable(obj);
            strings.add(str);
        }
        return strings;
    }

    @Override
    public String getModelDefaultValue(MModel mModel) {
        StringBuilder stringBuilder=new StringBuilder();
        if(mModel.getModelJson()!=null){
            JSONArray array=JSONArray.parseArray(mModel.getModelJson());
            for (int i = 0; i < array.size(); i++) {
                JSONObject obj=array.getJSONObject(i);
                String field=obj.getString("field");
                String defaultValue=obj.getString("defaultValue");
                defaultValue =defaultValue==null ? "''":defaultValue;
                stringBuilder.append(field).append(":").append(defaultValue).append("\n").append(",");
            }
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        }
        return stringBuilder.toString();
    }

    @Override
    public String getModelDefaultValueByArr(JSONArray array) {
        StringBuilder stringBuilder=new StringBuilder();
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj=array.getJSONObject(i);
            String field=obj.getString("field");
            String component=obj.getString("component");
            System.out.println(component);
            String defaultValue=obj.getString("defaultValue");
            defaultValue =defaultValue==null ? "''":defaultValue;
            if(component.equals(ModelComponentEnum.INPUT_NUM.getComponentType())){
                stringBuilder.append(field).append(":").append("Number(").append(defaultValue).append(")").append("\n").append(",");
            }else {
                stringBuilder.append(field).append(":").append(defaultValue).append("\n").append(",");
            }

        }
        stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        return stringBuilder.toString();
    }

    @Override
    public JSONArray getTableLabelByModel(JSONArray array) {
        JSONArray arr=new JSONArray();
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj=array.getJSONObject(i);
            JSONObject json=new JSONObject();
            String fieldName=obj.getString("fieldName");
            String field=obj.getString("field");
            json.put("label",fieldName);
            json.put("value",field);
            json.put("key",field);
            arr.add(json);
        }
        return arr;
    }

    @Override
    public List<Map<String,String>> getTableLabelByModel(MModel mModel) {
        List<Map<String,String>> arr=new ArrayList<>();
        JSONArray array=JSONArray.parseArray(mModel.getModelJson());
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj=array.getJSONObject(i);
            String field=obj.getString("field");
            String fieldName=obj.getString("fieldName");
            Map<String,String> stringMap=new HashMap<>();
            stringMap.put("field",field);
            stringMap.put("fieldName",fieldName);
            arr.add(stringMap);
        }
        return arr;
    }

    @Override
    public List<String> getTableFieldsByModel(MModel mModel) {
        String jsonStr=mModel.getModelJson();
        List<String> strs=new ArrayList<String>();
        JSONArray array=JSONArray.parseArray(jsonStr);
        for (int i = 0; i < array.size(); i++) {
            JSONObject json = array.getJSONObject(i);
            String field=json.getString("field");
            strs.add(field);
        }
        return strs;
    }

    @Override
    public List<String> getSumTableFieldsByModel(MModel mModel) {
        String jsonStr=mModel.getLieSumField();
        JSONArray array = JSONArray.parseArray(jsonStr);
        List<String> strs=new ArrayList<String>();
        for (int i = 0; i < array.size(); i++) {
            strs.add(array.getString(i));
        }
        return strs;
    }

    @Override
    public Map<String,String> getAllFormulations(MModel mModel) {
       Map<String, String> map = new HashMap<String, String>();
        if(mModel.getModelJson()!=null) {
            JSONArray array = JSONArray.parseArray(mModel.getModelJson());
            List<String> fields = new ArrayList<>();
            for (int i = 0; i < array.size(); i++) {
                JSONObject obj = array.getJSONObject(i);
                fields.add(obj.getString("field"));
            }
            for (int j = 0; j < array.size(); j++) {
                JSONObject obj = array.getJSONObject(j);
                String component=obj.getString("component");
                String formulaStr=(String) obj.get("formulaStr");
                String field=obj.getString("field");
                if("formula".equals(component)){
                    if(StringUtils.isNotBlank(formulaStr) && !"none".equals(formulaStr)){
                        map.put(field,formulaStr);
                    }
                }
            }
        }
        return map;
    }

    @Override
    public Map<String, String> getAllFormulations(JSONArray array) {
        Map<String, String> map = new HashMap<String, String>();
        if(array==null){
            return map;
        }
        List<String> fields = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj = array.getJSONObject(i);
            fields.add(obj.getString("field"));
        }
        for (int j = 0; j < array.size(); j++) {
            JSONObject obj = array.getJSONObject(j);
            String component = obj.getString("component");
            String formulaStr = (String) obj.get("formulaStr");
            String field = obj.getString("field");
            if ("formula".equals(component)) {
                if (StringUtils.isNotBlank(formulaStr) && !"none".equals(formulaStr)) {
                    map.put(field, formulaStr);
                }
            }
        }
        return map;
    }

    @Override
    public void formulationsDealData(Map<String, String> map, JSONArray array) {
        if(map==null || map.isEmpty()){
            return;
        }
        if(array==null || array.isEmpty()){
            return;
        }
        for (int i = 0; i < array.size() ; i++) {
            JSONObject obj = array.getJSONObject(i);
            map.forEach((k,v)->{
                Object val=FormulaUtils.count(obj,v);
                obj.put(k,val);
            });
        }
    }

    @Override
    public JSONArray getModelArray(MModel mModel) {
        if(mModel.getModelJson()==null){
            return new JSONArray();
        }
        JSONArray array=JSONArray.parseArray(mModel.getModelJson());
        return array;
    }

    @Override
    public JSONArray getArrayByModelDataType(JSONArray array, JSONArray model) {
        if(model==null || model.isEmpty()){
            return array;
        }
        if(array==null || array.isEmpty()){
            return array;
        }
        Map<String,String> dataType=new HashMap<>();
        for (int i = 0; i < model.size(); i++) {
            JSONObject obj=model.getJSONObject(i);
            String field=(String)obj.get("field");
            String component=(String)obj.get("component");
            if("input_num".equals(component)){
                dataType.put(field,"num");
            }
        }
        if(dataType.isEmpty()){
            return array;
        }
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj = array.getJSONObject(i);
            dataType.forEach((k,v)->{
                if("num".equals(v)){
                    obj.put(k,obj.getDouble(k));
                }
            });
        }
        return array;
    }

    @Override
    public void sort(JSONArray model) {
        if(model==null || model.size() == 0){
            return;
        }
        List<JSONObject> jsonObjects=new ArrayList<>();
        for (int i = 0; i < model.size(); i++) {
            JSONObject jsonObject= (JSONObject) model.get(i);
            jsonObjects.add(jsonObject);
        }
        model.clear();
        // 根据字段age进行排序
        Collections.sort(jsonObjects, new Comparator<JSONObject>() {
            @Override
            public int compare(JSONObject o1, JSONObject o2) {
                Integer sort1 = o1.getInteger("sort");
                Integer sort2 = o2.getInteger("sort");
                return sort1 - sort2;
            }
        });
        for(int i = 0; i < jsonObjects.size(); i++){
            JSONObject obj=jsonObjects.get(i);
            model.add(obj);
        }
    }

    @Autowired
    private MDictiService mDictiService;

    public String createTable(JSONObject obj){
        StringBuilder sb = new StringBuilder();
        String fieldName=obj.getString("fieldName");
        String field=obj.getString("field");
        String width=obj.getString("width");
        sb.append("<el-table-column");
        sb.append(empty_table_).append("prop=").append("\"").append(field).append("\"");
        sb.append(empty_table_).append("label=").append("\"").append(fieldName).append("\"");
        sb.append(empty_table_).append("width=").append("\"").append(width).append("\"").append(">");
        sb.append(empty_table_).append("</el-table-column>");
        return sb.toString();
    }

    public String createComponent(JSONObject obj,List<String> fields){
        StringBuilder sb = new StringBuilder();
        StringBuilder other=null;
        StringBuilder str=null;
        String fieldName=obj.getString("fieldName");
        String field=obj.getString("field");
        String component=obj.getString("component");
        String dictKey=(String) obj.get("dictKey");
        String formulaStr=(String) obj.get("formulaStr");
        String width=obj.getString("width");
        String defaultValue=obj.getString("defaultValue");
        String tag="";
        sb.append("<el-table-column");
        sb.append(empty_table_).append("label=").append("\"").append(fieldName).append("\"");
        sb.append(empty_table_).append("width=").append("\"").append(width).append("\"").append(">");
        sb.append(empty_table_).append(empty_table).append("<template slot-scope=\"scope\">").append("\n");
        String v_model=null;
        if("input_text".equals(component)){
            tag="el-input";
        }else if("select".equals(component)){
            str=new StringBuilder();
            tag="el-select";
            if(StringUtils.isNotBlank(String.valueOf(dictKey)) && !"none".equals(dictKey)){
                List<Map<String,Object>> mapList=mDictiService.getLabelDicts(String.valueOf(dictKey));
                if(mapList.size()==0){
                    str.append(empty_table_).append(empty_table).append(empty_table).append("<el-option");
                    str.append(empty_table_).append(empty_table).append(empty_table).append("size=\"small\"");
//                str.append(empty_table_).append(empty_table).append(empty_table).append("v-for=\"item in list_").append(field).append("\"");
//                str.append(empty_table_).append(empty_table).append(empty_table).append(":key=\"item.key\"");
                    str.append(empty_table_).append(empty_table).append(empty_table).append("label=\"空\"");
                    str.append(empty_table_).append(empty_table).append(empty_table).append("value=\"空\"").append(" >");
                    str.append(empty_table_).append(empty_table).append(empty_table).append("</el-option>");
                }else {
                    for (int i = 0; i < mapList.size(); i++) {
                        Map<String, Object> map = mapList.get(i);
                        String key=(String) map.get("key");
                        String value=(String)map.get("value");
                        str.append(empty_table_).append(empty_table).append(empty_table).append("<el-option");
                        str.append(empty_table_).append(empty_table).append(empty_table).append("size=\"small\"");
//                        str.append(empty_table_).append(empty_table).append(empty_table).append("key=\"").append(key).append("\"");
                        str.append(empty_table_).append(empty_table).append(empty_table).append("label=\"").append(value).append("\"");
                        str.append(empty_table_).append(empty_table).append(empty_table).append("value=\"").append(key).append("\"").append(" >");
                        str.append(empty_table_).append(empty_table).append(empty_table).append("</el-option>");
                    }
                }
            }else {
                str.append(empty_table_).append(empty_table).append(empty_table).append("<el-option");
                str.append(empty_table_).append(empty_table).append(empty_table).append("size=\"small\"");
//                str.append(empty_table_).append(empty_table).append(empty_table).append("v-for=\"item in list_").append(field).append("\"");
//                str.append(empty_table_).append(empty_table).append(empty_table).append(":key=\"item.key\"");
                str.append(empty_table_).append(empty_table).append(empty_table).append("label=\"未配置字典\"");
                str.append(empty_table_).append(empty_table).append(empty_table).append("value=\"未配置字典\"").append(" >");
                str.append(empty_table_).append(empty_table).append(empty_table).append("</el-option>");
            }

        }else if("date".equals(component)){
            other=new StringBuilder();
            tag="el-date-picker";
            other.append(" type=\"date\"").append(" ");
        }else if ("datetime".equals(component)){
            other=new StringBuilder();
            tag="el-date-picker";
            other.append(" type=\"datetime\" ");
        }else if("formula".equals(component)){
            tag = "a";
            str=new StringBuilder();
            if(StringUtils.isNotBlank(formulaStr) && !"none".equals(formulaStr)){
               // String s=FormulaUtils.formatVueVariable(fields,formulaStr,"scope.row.");

            //    str.append("{{ ").append(s).append(" }}");
                str.append("{{ scope.row.").append(field).append(" }}");
            }else {
                str.append("{{ scope.row.").append(field).append(" }}");
            }
        }else if("input_num".equals(component)){
            tag="el-input";
            other=new StringBuilder();
            other.append(" type=\"number\" ");
            other.append(" onkeyup=\"value=value.replace(/[^\\d]/g,' ')\" ");
        }
        sb.append(empty_table_).append("               <").append(tag).append("  size=\"small\"  ");
        if(v_model!=null){
//            sb.append(" :value=").append("\"").append(v_model).append("\" ");
        }else {
            sb.append(" v-model=\"scope.row.").append(field).append("\" ");
        }

        if(other!=null){
            sb.append(other.toString());
        }
        sb.append(">");
        if(str!=null){
            sb.append(str.toString());
        }
        sb.append(empty_table_).append(empty_table).append("</").append(tag).append(">");
        sb.append(empty_table_).append(empty_table).append("</template>");
        sb.append(empty_table_).append("</el-table-column>");
        return sb.toString();
    }


}




